package cn.jbolt.core.db.datasource;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.jbolt.core.model.DatasourceFilter;
import com.alibaba.fastjson.annotation.JSONField;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Config;
import com.jfinal.plugin.activerecord.generator.TableMeta;

import java.io.Serializable;
import java.util.List;
import java.util.function.Predicate;
/**
 * 平台数据源
 * @ClassName:  JBoltDatasource
 * @author: JFinal学院-小木 QQ：909854136
 * @date:  2021年9月25日16:44:17
 */
public class JBoltDatasource implements Serializable{
	private static final long serialVersionUID = -5038362515266104379L;
	/**
	 * 数据源名称
	 */
	private String name;
	/**
	 * 数据库类型
	 */
	private String dbType;
	/**
	 * 数据库名 (如果有)
	 */
	private String dbName;
	/**
	 * 数据库架构 (如果有)
	 */
	private String dbSchema;
	/**
	 * 链接地址
	 */
	private String jdbcUrl;
	/**
	 * 用户名
	 */
	private String user;
	/**
	 * id生成策略
	 */
	private String idGenMode;
	/**
	 * model生成package
	 */
	private List<String> modelPackages;
	/**
	 * jfinal持有的config配置
	 */
	private Config config;
	/**
	 * 描述备注
	 */
	private String remark;
	/**
	 * 表
	 */
	private List<TableMeta> tables;

	/**
	 * 是否为主数据源
	 */
	private boolean isMainDatasource;

	/**
	 * 数据源相关过滤器配置
	 */
	private DatasourceFilter datasourceFilter;
	public String getDbName() {
		return dbName;
	}
	public void setDbName(String dbName) {
		this.dbName = dbName;
	}
	public String getDbSchema() {
		return dbSchema;
	}
	public void setDbSchema(String schema) {
		this.dbSchema = schema;
	}
	public String getJdbcUrl() {
		return jdbcUrl;
	}
	public void setJdbcUrl(String jdbcUrl) {
		this.jdbcUrl = jdbcUrl;
	}
	public String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public String getIdGenMode() {
		return idGenMode;
	}
	public void setIdGenMode(String idGenMode) {
		this.idGenMode = idGenMode;
	}
	@JSONField(serialize = false)
	public Config getConfig() {
		return config;
	}
	public void setConfig(Config config) {
		this.config = config;
	}
	public boolean getIsMainDatasource() {
		return isMainDatasource;
	}
	public void setIsMainDatasource(boolean isMainDatasource) {
		this.isMainDatasource = isMainDatasource;
	}
	public String getDbType() {
		return dbType;
	}
	public void setDbType(String dbType) {
		this.dbType = dbType;
	}
	public String getRemark() {
		return remark;
	}
	public void setRemark(String remark) {
		this.remark = remark;
	}
	public List<String> getModelPackages() {
		return modelPackages;
	}
	public void setModelPackages(List<String> modelPackages) {
		this.modelPackages = modelPackages;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@JSONField(serialize = false)
	public List<TableMeta> getTables() {
		return tables;
	}
	public void setTables(List<TableMeta> tables) {
		this.tables = tables;
	}

	public boolean hasTables() {
		return tables!=null&&tables.size()>0;
	}
	@JSONField(serialize = false)
	public int getTableSize() {
		return tables==null?0:tables.size();
	}
	@JSONField(serialize = false)
	public DatasourceFilter getDatasourceFilter() {
		return datasourceFilter;
	}
	public void setDatasourceFilter(DatasourceFilter datasourceFilter) {
		this.datasourceFilter = datasourceFilter;
	}
	/**
	 * 获取表过滤规则
	 * @return
	 */
	@JSONField(serialize = false)
	public Predicate<String> getTableSkipPredicate() {
		if(datasourceFilter == null) {
			JBoltDataSourceUtil.me.processDataSourceFilter(this);
		}
		if(datasourceFilter == null) {
			return new Predicate<String>() {
				@Override
				public boolean test(String tableName) {
					tableName=tableName.toLowerCase();
//					if(tableNames!=null && tableNames.length>0) {
//						return ArrayUtil.containsIgnoreCase(tableNames, tableName) == false;
//					}
					if(tableName.startsWith("jb_")) {
						return true;
					}
					return tableNameFilter(StrUtil.splitToArray(DatasourceFilterService.defaultTableNameFilters, ","),tableName)||tableNameContain(StrUtil.splitToArray(DatasourceFilterService.defaultTableNameContains, ","),tableName) || tableNamePatternsMatch(StrUtil.splitToArray(DatasourceFilterService.defaultTableNamePatterns, ","),tableName);
				}
			};
		}

		return new Predicate<String>() {
			@Override
			public boolean test(String tableName) {
				tableName=tableName.toLowerCase();
//				if(tableNames!=null && tableNames.length>0) {
//					return ArrayUtil.containsIgnoreCase(tableNames, tableName) == false;
//				}
				if(tableName.startsWith("jb_")) {
					return true;
				}
				return tableNameFilter(StrUtil.splitToArray(datasourceFilter.getTableNameFilter(), ","),tableName)||tableNameContain(StrUtil.splitToArray(datasourceFilter.getTableNameContains(), ","),tableName)||tableNamePatternsMatch(StrUtil.splitToArray(datasourceFilter.getTableNamePatterns(), ","),tableName);
			}
		};
	}

	/**
	 * 获取表过滤规则 文档用
	 * @return
	 */
	public Predicate<String> _getDevDocTableSkipPredicate() {
		if(datasourceFilter == null) {
			JBoltDataSourceUtil.me.processDataSourceFilter(this);
		}

		String nameContaines = datasourceFilter==null?DatasourceFilterService.defaultTableNameContains:datasourceFilter.getTableNameContains();
		if(nameContaines!=null){
			if(nameContaines.toLowerCase().equalsIgnoreCase("jb_")){
				nameContaines = "";
			}else if(nameContaines.toLowerCase().startsWith("jb_")){
				nameContaines = nameContaines.substring(3);
			}else if(nameContaines.toLowerCase().endsWith("jb_")) {
				nameContaines = nameContaines.substring(0,nameContaines.length()-4);
			}else if(nameContaines.contains(",jb_,")){
				nameContaines = nameContaines.replace(",jb_,",",");
			}else if(nameContaines.contains(",JB_,")){
				nameContaines = nameContaines.replace(",JB_,",",");
			}
		}

		if(datasourceFilter == null) {
			String finalNameContaines = nameContaines;
			return new Predicate<String>() {
				@Override
				public boolean test(String tableName) {
					tableName=tableName.toLowerCase();
					return tableNameFilter(StrUtil.splitToArray(DatasourceFilterService.defaultTableNameFilters, ","),tableName)||tableNameContain(StrUtil.splitToArray(finalNameContaines, ","),tableName) || tableNamePatternsMatch(StrUtil.splitToArray(DatasourceFilterService.defaultTableNamePatterns, ","),tableName);
				}
			};
		}


		String finalNameContaines1 = nameContaines;
		return new Predicate<String>() {
			@Override
			public boolean test(String tableName) {
				tableName=tableName.toLowerCase();
				return tableNameFilter(StrUtil.splitToArray(datasourceFilter.getTableNameFilter(), ","),tableName)||tableNameContain(StrUtil.splitToArray(finalNameContaines1, ","),tableName)||tableNamePatternsMatch(StrUtil.splitToArray(datasourceFilter.getTableNamePatterns(), ","),tableName);
			}
		};
	}



	/**
	 * 判断表名是否包含指定自定义字符串
	 * @param tableNameContains
	 * @param tableName
	 * @return
	 */
	public static boolean tableNameContain(String[] tableNameContains,String tableName) {
		boolean in=false;
		for(String str:tableNameContains) {
			if(tableName.indexOf(str)!=-1) {
				in=true;
				break;
			}
		}
		return in;
	}
	/**
	 * 判断表名符合正则
	 * @param tableNamesPatterns
	 * @param tableName
	 * @return
	 */
	private boolean tableNamePatternsMatch(String[] tableNamesPatterns,String tableName) {
		boolean in=false;
		for(String p:tableNamesPatterns) {
			if(tableName.matches(p)) {
				in=true;
				break;
			}
		}
		return in;
	}
	/**
	 * 判断是否在完整过滤表名中存在
	 * @param tableNameFilters
	 * @param tableName
	 * @return
	 */
	private boolean tableNameFilter(String[] tableNameFilters,String tableName) {
		return ArrayUtil.containsIgnoreCase(tableNameFilters, tableName);
	}
	public void clearTables() {
		if(hasTables()) {
			tables.clear();
			tables = null;
		}
	}

	public String getOptionText() {
		return name+(StrKit.isBlank(remark)?"":("["+remark+"]"))+"_"+dbType;
	}

}
